package net.pws.oos.biz;

import java.text.MessageFormat;

import net.pws.oos.biz.model.Identifier;
import net.pws.oos.biz.model.Organization;

import org.apache.commons.lang.StringUtils;

public class EntityUtils {
    
    /**
     * 判断两个实体是否相等<br>
     * 如果两个实体都为null，返回ture<br>
     * 如果两个实体的ID都为null，返回false<br>
     * 其余情况基本按照ID比较
     * 
     * @param id1
     * @param id2
     * @return
     */
    public static boolean isEqual(Identifier id1, Identifier id2) {
        if (id1 == id2) {
            return true;
        }
        else if (id1 == null && id2 != null) {
            return false;
        }
        else if (id1 != null && id2 == null) {
            return false;
        }
        else if (id1.getId() == null || id2.getId() == null) {
            return false;
        }
        else {
            return id1.getId().equals(id2.getId());
        }
    }
    
    // =================建设单位树形编码维护==================
    /**
     * 判断是否子孙的编码
     * 
     * @param parentCode
     *            父编码
     * @param parentDepth
     *            父深度
     * @param subCode
     *            子编码
     * @return
     */
    public static boolean isSubInnerCode(String parentCode,
                                         int parentDepth,
                                         String subCode) {
        if (parentCode.length() >= subCode.length()) {
            return false;
        }
        String validParent = getValidInnerCode(parentCode, parentDepth);
        String subValidParent = getValidInnerCode(subCode, parentDepth);
        return validParent.equals(subValidParent);
    }
    
    /**
     * 得到指定某层级的有效编码
     * 
     * @param code
     * @param depth
     * @return
     */
    public static String getValidInnerCode(String code, int depth) {
        checkInnerCode(code);
        if (code.length() < (depth + 1) * Organization.INNER_CODE_UNIT_LENGTH) {
            throw new BizException(MessageFormat.format("内部编码[{0}]的长度小于指定深度[{1}]的长度！",
                                                        code,
                                                        depth));
        }
        return code.substring(0,
                              (depth + 1) * Organization.INNER_CODE_UNIT_LENGTH);
    }
    
    /*
     * 检查指定的内部编码是否正确，如果否则抛出异常
     */
    private static void checkInnerCode(String code) {
        if (code == null || code.length() % Organization.INNER_CODE_UNIT_LENGTH != 0) {
            throw new BizException(MessageFormat.format("内部编码[{0}]不正确！", code));
        }
    }
    
    /**
     * 根据编码最大的兄弟节点，计算出内部编码
     * 
     * @param brotherCode
     *            兄弟节点编码
     * @param depth
     *            当前节点深度
     * @return
     */
    public static String plusInnerCode(String brotherCode, int depth) {
        String parentValid = getValidInnerCode(brotherCode, depth - 1);
        String code = brotherCode.substring(parentValid.length(),
                                            (depth + 1) * Organization.INNER_CODE_UNIT_LENGTH);
        int order = Integer.parseInt(code) + 1;
        code = parentValid + StringUtils.leftPad(order + "",
                                                 Organization.INNER_CODE_UNIT_LENGTH,
                                                 Organization.INNER_CODE_FILL);
        checkInnerCode(code);
        return code;
    }
    
    /**
     * 对于没有兄弟的节点，计算新的内部编码
     * 
     * @param parentCode
     *            父节点编码
     * @param depth
     *            当前节点深度
     * @return
     */
    public static String newInnerCode(String parentCode, int depth) {
        String code;
        if (StringUtils.isEmpty(parentCode)) {
            code = StringUtils.leftPad("1",
                                       Organization.INNER_CODE_UNIT_LENGTH,
                                       Organization.INNER_CODE_FILL);
        }
        else {
            String parentValid = getValidInnerCode(parentCode, depth - 1);
            code = parentValid + StringUtils.leftPad("1",
                                                     Organization.INNER_CODE_UNIT_LENGTH,
                                                     Organization.INNER_CODE_FILL);
        }
        
        checkInnerCode(code);
        return code;
    }
    
    /**
     * 根据父节点的新编码与子节点的原编码，计算子节点的新编码
     * 
     * @param parentCode
     *            父编码
     * @param parentDepth
     *            父深度
     * @param oldCode
     *            原来的子编码
     * @param oldDepth
     *            原来的子深度
     * @return
     */
    public static String updateInnerCode(String parentCode,
                                         int parentDepth,
                                         String oldCode,
                                         int oldDepth) {
        String validParent = getValidInnerCode(parentCode, parentDepth);
        String subCode = oldCode.substring(oldDepth * Organization.INNER_CODE_UNIT_LENGTH,
                                           (oldDepth + 1) * Organization.INNER_CODE_UNIT_LENGTH);
        subCode = validParent + subCode;
        checkInnerCode(subCode);
        return subCode;
    }
}
